#pragma once
#include<iostream>
#include<cerrno>
#include"Protocol.hpp"
#include"Calculate.hpp"
#include"Log.hpp"
#include"Connection.hpp"

using namespace Protocol;
using namespace CalCulateNS;

const static int buffer_size=1024;

class HandlerConnection
{
    public:
    static void HandlerRequest(Connection *conn)
    {
        std::string &inbuffer=conn->InBuffer();
        std::string message; // 表示一个符合协议的一个完整的报文
        Calculate cal;
        Factory factory;
        auto req=factory.BuildRequest();
        while(Decode(inbuffer,&message))
        {
            if(!req->Deserialize(message))
            continue;
            //处理
            auto resp=cal.Cal(req);

            std::string responseStr;
            resp->Serialize(&responseStr);
            responseStr=Encode(responseStr);
            conn->AddOutBuffer(responseStr);
        }

        if(!conn->OutBufferEmpty())
        {
            conn->_sender(conn);   // 对写事件，直接发！！！--- 不代表能全部发完！
        }

    }

    // static void Sender(Connection* conn)
    // {
    //     errno=0;
    //     std::string &outbuffer=conn->OutBuffer();
    //     while(true)
    //     {
    //         ssize_t n=::send(conn->SockFd(),&outbuffer,outbuffer.size(),0);
    //         if (n >= 0)
    //         {
    //             outbuffer.erase(0, n);
    //             if (outbuffer.empty())
    //                 break;
    //         }
    //         else
    //         {
    //             if (errno = EAGAIN)
    //                 break;
    //             else if(errno==EINTR)
    //             continue;
    //             else
    //             {
    //                 conn->_excepter(conn);
    //                 return;
    //             }
    //         }
    //     }
        
    // }

    static void Recver(Connection *conn)
    {
        // 清除错误号，确保它不是从之前的操作中设置的。
        errno = 0;
        char buffer[buffer_size];
         std::cout<<"我开始读了\n";
        while(true)
        {
            ssize_t  n=::recv(conn->SockFd(),buffer,sizeof(buffer)-1,0);
            if(n>0)
            {
                buffer[n]=0;
                conn->AddInBuffer(buffer);
            }
            else
            {
                std::cout<<"没读到数据\n";
                if(errno==EAGAIN)
                break;
                else if(errno==EINTR)
                continue;
                else
                {
                    conn->_excepter(conn);
                    return;
                }

            }

        }
        std::cout << "sockfd# " << conn->SockFd() << ":\n"
                  << conn->InBuffer() << std::endl;
        // 尝试分析处理报文 -- 半个，一个半， 10个，11个半
        HandlerRequest(conn);

    }
    static void Sender(Connection *conn)
    {
        // 清除错误号，确保它不是从之前的操作中设置的。
        errno = 0;

        // 获取连接对象的输出缓冲区引用。
        std::string &outbuffer = conn->OutBuffer();

        // 无限循环，直到没有数据需要发送或发生错误。
        while (true)
        {
            // 尝试通过套接字文件描述符发送输出缓冲区中的数据。
            ssize_t n = ::send(conn->SockFd(), &outbuffer[0], outbuffer.size(), 0);

            // 如果发送成功，并且发送了至少一个字节的数据。
            if (n >= 0)
            {
                // 从输出缓冲区删除已发送的数据。
                outbuffer.erase(0, n);

                // 如果输出缓冲区为空，则退出循环。
                if (outbuffer.empty())
                    break;
            }
            // 如果发送失败。
            else
            {
                // 如果错误号是 EAGAIN（资源暂时不可用），则退出循环。
                if (errno == EAGAIN)
                    break;
                // 如果错误号是 EINTR（系统调用被中断），则继续尝试发送。
                else if (errno == EINTR)
                    continue;
                // 其他错误情况下，调用异常处理函数并返回。
                else
                {
                    conn->_excepter(conn);
                    return;
                }
            }
        }
        // 走到这里，意味着什么？我们本轮发满了，但是数据可能没发完，为什么没发完呢？
        // 开启对conn->SockFd() EPOLLOUT的关心！！！！！， 如何开启对于特定一个connection对应的写事件关心呢？？？
        if (!conn->OutBufferEmpty())
        {
            conn->_R->EnableReadWrite(conn->SockFd(), true, true);
        }
        else
        {
            conn->_R->EnableReadWrite(conn->SockFd(), true, false);
        }
    }
    static void excepter(Connection *conn)
    {
        lg.LogMessage(Info,"connection erase done,who : %d\n",conn->SockFd());
        errno=0;
        //从epoll中移除对fd的关心
        conn->_R->RemoveConnection(conn->SockFd());
        //关闭fd
        conn->Close();
        delete conn;
    }

};